<?php
require_once ('class_managed_form.php');

class VersionedManagedForm extends ManagedForm
{
  const MODE_REVERT = 4;
  const PARAM_MODE_REVERT = 'r';
  const FEEDBACK_REVERT = 'Record successfully reverted, redirecting...';

  protected $revertId;

  public function __construct($mysqlTable, $mysqlDatabase = null)
  {
    parent::__construct($mysqlTable, 'group_id', $mysqlDatabase);
  }

  protected function validateInput()
  {
    parent::validateInput();
    if (isset($_GET[self::PARAM_MODE_EDIT]) &&
        isset($_GET[self::PARAM_MODE_REVERT])) {
      $this->mode = self::MODE_REVERT;
      $this->rowId = mysql_real_escape_string($_GET[self::PARAM_MODE_EDIT]);
      $this->revertId =
          mysql_real_escape_string($_GET[self::PARAM_MODE_REVERT]);
      $this->feedback = self::FEEDBACK_REVERT;
    }
    $this->validateTableStructure();
  }

  protected function validateTableStructure()
  {
    $result = Util::query("SHOW COLUMNS FROM " . $this->mysqlFrom);

    list($name, $type, $null, $key, $default, $extra) =
        mysql_fetch_array($result, MYSQL_NUM);
    if ($name !== 'id' || strpos($type, 'int') !== 0 ||
        $extra !== 'auto_increment') {
      throw new LogicException('Column 1 in the specified table should be ' .
          'named \'id\', should be of type \'int\', and should be set to ' .
          '\'auto_increment\'');
    }

    list($name, $type, $null, $key, $default, $extra) =
        mysql_fetch_array($result, MYSQL_NUM);
    if ($name !== 'group_id' ||  strpos($type, 'int') !== 0) {
      throw new LogicException('Column 2 in the specified table should be ' .
          'named \'group_id\' and should be of type \'int\'');
    }

    list($name, $type, $null, $key, $default, $extra) =
        mysql_fetch_array($result, MYSQL_NUM);
    if ($name !== 'current' || $type !== 'tinyint(1)') {
      throw new LogicException('Column 3 in the specified table should be ' .
          'named \'current\' and should be of type \'tinyint(1)\'');
    }

    list($name, $type, $null, $key, $default, $extra) =
        mysql_fetch_array($result, MYSQL_NUM);
    if ($name !== 'timestamp' || strpos($type, 'int') !== 0) {
      throw new LogicException('Column 4 in the specified table should be ' .
          'named \'timestamp\' and should be of type \'int\'');
    }

    list($name, $type, $null, $key, $default, $extra) =
        mysql_fetch_array($result, MYSQL_NUM);
    if ($name !== 'edited_by' || $type != 'text') {
      throw new LogicException('Column 5 in the specified table should be ' .
          'named \'edited_by\' and should be of type \'text\'');
    }
  }

  public function loadElements()
  {
    parent::loadElements();
    $this->setElementType('group_id', 'HiddenElement');
    $this->setElementType('current', 'HiddenElement');
    $this->setElementType('timestamp', 'HiddenElement');
    $this->setElementType('edited_by', 'HiddenElement');

    $this->setRequired(array('group_id', 'current', 'timestamp', 'edited_by'),
        false);
  }

  protected function loadDefaultValues()
  {
    if ($this->mode == self::MODE_REVERT) {
      $result = Util::query("SELECT *
                            FROM $this->mysqlFrom
                            WHERE id = '$this->revertId'");
    } else {
      $result = Util::query("SELECT *
                            FROM $this->mysqlFrom
                            WHERE $this->mysqlPrimaryKey = '$this->rowId'
                            AND current = 1");
    }
    if (mysql_num_rows($result) !== 1) {
      throw new UnexpectedValueException('Failed to retrieve default values');
    } else {
      $this->defaultValues = mysql_fetch_array($result, MYSQL_ASSOC);
    }
  }

  public function display()
  {
    parent::display();
    $this->loadPreviousVersions();
  }

  protected function loadPreviousVersions()
  {
    $result = Util::query("SELECT id, timestamp, edited_by
                           FROM $this->mysqlFrom
                           WHERE $this->mysqlPrimaryKey = '$this->rowId'
                           AND current = 0
                           ORDER BY timestamp DESC");
    if (mysql_num_rows($result) > 0) {
      echo "<script type=\"text/javascript\">\n";
      while (list($id, $timestamp, $edited_by) = mysql_fetch_array($result)) {
        echo "formSystem.addVersion(" .
            "new VersionInfo('$id', '$timestamp', '$edited_by'));\n";
      }
      echo "</script>\n";
    }
  }

  public function submit()
  {
    /* Remove the current flag from the previous entry */
    if ($this->mode == self::MODE_EDIT || $this->mode == self::MODE_DELETE ||
        $this->mode == self::MODE_REVERT) {
      $query = "UPDATE $this->mysqlFrom
                SET current = 0
                WHERE current = 1
                AND $this->mysqlPrimaryKey = '$this->rowId'
                LIMIT 1";
      $this->debugPrint("CURRENT QUERY: $query");
      if (!$this->debug) {
        Util::query($query);
      }
    }

    /* When we're creating a whole new record, generate a new group id */
    if ($this->mode == self::MODE_ADD || $this->mode == self::MODE_COPY) {
      $result = Util::query("SELECT MAX(group_id) FROM $this->mysqlFrom");
      $nextGroupId = mysql_fetch_row($result);
      $this->getElement('group_id')->setValue($nextGroupId[0] + 1);
    }

    /* For every mode but delete we'll be inserting a new row */
    if ($this->mode == self::MODE_ADD || $this->mode == self::MODE_EDIT ||
        $this->mode == self::MODE_COPY || $this->mode == self::MODE_REVERT) {

      /* Insert the new current entry */
      $this->getElement('current')->setValue('1');
      $this->getElement('timestamp')->setValue(time());
      $this->getElement('edited_by')->setValue(Login::getUserName());

      /* Get a list of all the columns in the table */
      $result = Util::query("SHOW COLUMNS FROM " . $this->mysqlFrom);
      $tableColumns = array(); 
      while ($data = mysql_fetch_array($result, MYSQL_ASSOC)) {
        $tableColumns[] = $data['Field'];
      }

      /* Pop the 'id' field off the front of the array since it's automatic */
      array_shift($tableColumns);

      $query = "INSERT INTO $this->mysqlFrom VALUES('', ";
      $queryFields = array();
      foreach ($tableColumns as $columnName) {
        if ($this->hasElement($columnName)) {
          $element = $this->getElement($columnName);
          $value = Util::getMysqlSafeString($element->getValue());
          $queryFields[] = "'$value'";
        } else {
          $queryFields[] = "''";
        }
      }
      $query .= implode(', ', $queryFields) . ')';
      $this->debugPrint("MAIN QUERY: $query");
      if (!$this->debug) {
        Util::query($query);
      }
    }
  }
}
?>